﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Threading;  //usado para administrar los hilos
using System.Collections;  //usado para ArrayList
using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.
using System.Text.RegularExpressions; //usado para expresiones regulares. Filtrar descripciones
using SistemaCenterQuimPost.Control; //usado para validar datos.

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;

namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmGestionClientes : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //------------ATRIBUTOS--------------------
        protected DataSet3 clientesDs;  //Atributos usados para obtener datos de la base de datos.   

        protected DataSet3TableAdapters.ClientesTableAdapter clientesTa;

        protected bool refrescarResgClientes; //La primera vez debe refrescar el resgClientes.

        protected ArrayList resgClientes; // colección usada para guardar dni y apellidoNombre, se tiene una pequeña base de dato para realizar las busqueda mediante filtros más rapidamente.

        protected string[] resgClienteActual; //al ser una interface polifuncional. Guarda el cliente encontrado en una busqueda exitosa. {dni, nombreApellido, cuit, provincia, localidad, direccion, tel, cel, email, descuento}   

        protected Thread oHiloActualizarResgClientes; //hilos que son ejecutados concurrentemente con la aplicación.
        protected Thread oHiloFiltrarApellidoNombre;

        protected string estadoDelFormulario;  //estAgregar, estEditar, estBuscando 

        //------------CONSTRUCTORES---------------
        public frmGestionClientes()
        {
            InitializeComponent();

            estadoDelFormulario = "";

            refrescarResgClientes = true; //inicializamos a true, ya que la primera vez que trate de usar ResgClientes tendra que actualizar.

            //(ALE) COLOCAR BIEN ESTAS 2 INSTRUCCIONES SI ES QUE NO LO ESTÁN
            this.clientesDs = new DataSet3();

            this.clientesTa = new DataSet3TableAdapters.ClientesTableAdapter();

            this.resgClientes = new ArrayList();  //se inicializa la colección ArrayList que guardará una base de datos parcial.          
            this.resgClienteActual = new String[11];  //se inicializa el array de string que almacena el cliente actual.

            this.oHiloActualizarResgClientes = new Thread(new ThreadStart(actualizarResgClientes)); //Instancia el hilo y lo delega al metodo actualizarResgClientes. 
            this.oHiloFiltrarApellidoNombre = new Thread(new ThreadStart(filtrarApellidoNombre));
        }



        //------------ESTADOS---------------------
        protected void frmGestionClientes_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;  //necesario para trabajar con hilos.

            resguardarClienteActual(); //guarda el estado inicial del formulario.

            estEsperandoOperacion(); //estado al comenzar el formulario o al fracasar en la busqueda.
        }

        //virtual me permite redefinir, en este caso solo en las clases hijas
        protected virtual void estEsperandoOperacion() //estado luego de realizar una busqueda exitosa, agregar o editar. Es decir con datos en vista.
        {

            if (this.txtNombre.Text == "") //estado al iniciar el formulario
            {
                System.Windows.Forms.Control[] controlesHabilitados = { this.txtDni, this.btnBusDni, this.txtApellido, this.btnBusApellido, this.btnAgregar };
                System.Windows.Forms.Control[] controlesDeshabilitados = { this.txtNombre, this.txtCuit, this.txtProvincia, this.txtLocalidad, this.txtDireccion, this.txtTel, this.txtCel, this.txtEmail, this.txtDescuento, this.btnEditar, this.btnProcesar };
                System.Windows.Forms.Control[] controlesVisibles = { };
                System.Windows.Forms.Control[] controlesInvisibles = { lstClientesApellidoNombre, this.lblErrorDni, this.lblErrorApellido, this.lblErrorNombre, this.lblErrorDireccion, lblError };

                habilitarControles(controlesHabilitados);
                deshabilitarControles(controlesDeshabilitados);
                visibleControles(controlesVisibles);
                invisibleControles(controlesInvisibles);

                if (refrescarResgClientes) //si hace falta actualizar el refrescarResgClientes se realiza
                {
                    ejecutarHiloActualizarResgClientes();

                }

            }
            else   //estado luego de una busqueda.
            {
                System.Windows.Forms.Control[] controlesHabilitados = { this.txtDni, this.btnBusDni, this.txtApellido, this.btnBusApellido, this.btnAgregar, this.btnEditar };
                System.Windows.Forms.Control[] controlesDeshabilitados = { this.txtNombre, this.txtCuit, this.txtProvincia, this.txtLocalidad, this.txtDireccion, this.txtTel, this.txtCel, this.txtEmail, this.txtDescuento, this.btnProcesar };
                System.Windows.Forms.Control[] controlesVisibles = { };
                System.Windows.Forms.Control[] controlesInvisibles = { lstClientesApellidoNombre, this.lblErrorDni, this.lblErrorApellido, this.lblErrorNombre, this.lblErrorDireccion, lblError };

                habilitarControles(controlesHabilitados);
                deshabilitarControles(controlesDeshabilitados);
                visibleControles(controlesVisibles);
                invisibleControles(controlesInvisibles);

            }

            errorProvider1.Clear();  //se borran los errores, si habian.

            txtDni.Focus();   //se deja el foco en txtDni

            estadoDelFormulario = "estEsperandoOperacion";

        }

        protected virtual void estAgregar()
        {

            System.Windows.Forms.Control[] controlesHabilitados = { this.txtDni, this.txtApellido, this.txtNombre, this.txtCuit, this.txtProvincia, this.txtLocalidad, this.txtDireccion, this.txtTel, this.txtCel, this.txtEmail, this.txtDescuento, btnAgregar, this.btnProcesar };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.btnBusDni, this.btnBusApellido, btnEditar };
            System.Windows.Forms.Control[] controlesVisibles = { this.lblErrorDni, this.lblErrorApellido, this.lblErrorNombre, this.lblErrorDireccion };
            System.Windows.Forms.Control[] controlesInvisibles = { this.lstClientesApellidoNombre, lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            errorProvider1.Clear();

            txtDni.Focus();

            estadoDelFormulario = "estAgregar";
        }

        protected virtual void estEditar()
        {

            System.Windows.Forms.Control[] controlesHabilitados = { this.txtDireccion, this.txtTel, this.txtCel, this.txtEmail, btnEditar, this.btnProcesar };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.txtDni, this.btnBusDni, this.txtApellido, this.btnBusApellido, this.txtNombre, this.txtCuit, this.txtProvincia, this.txtLocalidad, this.txtDescuento, this.btnAgregar };
            System.Windows.Forms.Control[] controlesVisibles = { this.lblErrorDireccion};
            System.Windows.Forms.Control[] controlesInvisibles = { this.lstClientesApellidoNombre, this.lblErrorDni, this.lblErrorApellido, this.lblErrorNombre, lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            errorProvider1.Clear();

            txtDni.Focus();

            estadoDelFormulario = "estEditar";
        }

        //---------METODOS VARIOS-----------------

        protected virtual void vaciarTextBox() //Se deja en blanco todos los textBox, usado en estados estInicial y estAgregar.
        {
            txtDni.Text = "";
            txtApellido.Text = "";
            txtNombre.Text = "";
            txtCuit.Text = "";
            txtProvincia.Text = "";
            txtLocalidad.Text = "";
            txtDireccion.Text = "";
            txtTel.Text = "";
            txtCel.Text = "";
            txtEmail.Text = "";
            txtDescuento.Text = "0";

        }

        //Virtual, permite redefinir en sus hijos
        protected virtual void actualizarResgClientes() //Se refresca el arrayList resgClientes
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ClientesTa.FillByClientes(centerQuimDs,...);
                clientesTa.Fill(clientesDs.Clientes);

                resgClientes.Clear(); //Se vacia resgclientes (ArrayList)

                foreach (DataRow unaFila in clientesDs.Clientes) //Se recorre todas las filas  del centerQuimDs.Clientes y se cargan los mismos al ArrayList
                {
                    resgClientes.Add(new Cliente(Convert.ToString(unaFila[0]), Convert.ToString(unaFila[1])));
                }

                refrescarResgClientes = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber clientes cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }

        }

        private void btnBusDni_Click(object sender, EventArgs e)  //metodo capturador del evento click sobre la lupa (btnBusDni)
        {
            eventoBusDni();
        }

        protected virtual void eventoBusDni()  //Se encapsula en un método para que pueda usar cuando se presiona Enter sobre el txtDni en estado de busqueda o click en btnBusDni.
        {

            //no hace falta que pregunte si txtCDni es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgClientes)   //si es necesario actualizar el resgClientes se lo hace sino no
            {
                ejecutarHiloActualizarResgClientes();  //ejecuta el hilo que actualiza el ResgClientes
            }


            int contador = 0; //maneja el numero de iteraciones (busqueda dicotómica)
            bool encontrado = false; //maneja si fué encontrado el cliente

            do
            {
                if (((Cliente)resgClientes[contador]).Dni == txtDni.Text)
                {
                    encontrado = true;

                    break;

                }else
                {
                    contador++;
                }

            } while (contador < resgClientes.Count);


            if (encontrado)  //el filtro obtuvo coincidencias.
            {
                this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDni y lanzará el evento TextChanged()

                cargarClientePorDni(this.txtDni.Text.Trim());  //busca cliente con dni (una coincidencia) encontrado en el oHiloFiltrarDni y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

                resguardarClienteActual(); //Guarda los valores de los textBox luego de una busqueda exitosa.

            }

            else  //la busqueda obtuvo una coincidencia
            {

                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                deshacerCambios(); //coloca el estado de la ultima busqueda exitosa de un clientes.

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }

        }

        protected void ejecutarHiloActualizarResgClientes() // hilo para actualizar el atributo ResgClientes
        {
            if ((oHiloActualizarResgClientes.ThreadState == ThreadState.Unstarted) || (oHiloActualizarResgClientes.ThreadState == ThreadState.Stopped))
            {
                this.oHiloActualizarResgClientes = new Thread(new ThreadStart(actualizarResgClientes));
                this.oHiloActualizarResgClientes.Priority = ThreadPriority.Highest;
                this.oHiloActualizarResgClientes.Start();  //Se ejecuta el hilo para actualizar el atributo ResgClientes
            }
        }

        protected virtual void resguardarClienteActual() //Guarda los valores de los textBox en array resgClienteActual, luego de una busqueda exitosa.
        {
            resgClienteActual[0] = txtDni.Text;
            resgClienteActual[1] = txtApellido.Text;
            resgClienteActual[2] = txtNombre.Text;
            resgClienteActual[3] = txtCuit.Text;
            resgClienteActual[4] = txtProvincia.Text;
            resgClienteActual[5] = txtLocalidad.Text;
            resgClienteActual[6] = txtDireccion.Text;
            resgClienteActual[7] = txtTel.Text;
            resgClienteActual[8] = txtCel.Text;
            resgClienteActual[9] = txtEmail.Text;
            resgClienteActual[10] = txtDescuento.Text;

        }

        protected virtual void deshacerCambios()  //usado cuando en estado editar o agregar, se arrepiente (no se apreta en procesar) y se vuelve a estado esperandoOperacion.
        {
            txtDni.Text = resgClienteActual[0];
            txtApellido.Text = resgClienteActual[1];
            txtNombre.Text = resgClienteActual[2];
            txtCuit.Text = resgClienteActual[3];
            txtProvincia.Text = resgClienteActual[4];
            txtLocalidad.Text = resgClienteActual[5];
            txtDireccion.Text = resgClienteActual[6];
            txtTel.Text = resgClienteActual[7];
            txtCel.Text = resgClienteActual[8];
            txtEmail.Text = resgClienteActual[9];
            txtDescuento.Text = resgClienteActual[10];

        }

        protected virtual void cargarClientePorDni(string unDni) //busca cliente con dni (una coincidencia) encontrado en el oHiloFiltrarDni y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //clientesTa.FillByClientes(centerQuimDs,unDni);
                clientesTa.FillByDni(clientesDs.Clientes, unDni);

                //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada.
                txtDni.Text = clientesDs.Clientes[0].dni;

                int posBlanco = 0; //indica un numero de base cero, donde se encuentra el blanco entre apellido y nombre.
                posBlanco = clientesDs.Clientes[0].apellidoyNombre.IndexOf(" ");

                txtApellido.Text = clientesDs.Clientes[0].apellidoyNombre.Substring(0, posBlanco);
                txtNombre.Text = clientesDs.Clientes[0].apellidoyNombre.Substring(posBlanco + 1, clientesDs.Clientes[0].apellidoyNombre.Length - (posBlanco+1));

                txtCuit.Text = clientesDs.Clientes[0].cuit;
                txtProvincia.Text = clientesDs.Clientes[0].provincia;
                txtLocalidad.Text = clientesDs.Clientes[0].localidad;
                txtDireccion.Text = clientesDs.Clientes[0].direccion;
                txtTel.Text = clientesDs.Clientes[0].tel;
                txtCel.Text = clientesDs.Clientes[0].cel;
                txtEmail.Text = clientesDs.Clientes[0].email;
                txtDescuento.Text = clientesDs.Clientes[0].descuento.ToString();


                //...
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected virtual void cargarClientesPorApellidoNombre(string unApellidoNombre)  //busca el cliente por nombreApellido en la base de datos y lo carga en los textbox.
        {
            //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
            clientesTa.FillByApellidoNombre(clientesDs.Clientes, unApellidoNombre);

            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada.
            txtDni.Text = clientesDs.Clientes[0].dni;

            int posBlanco = 0; //indica un numero de base cero, donde se encuentra el blanco entre apellido y nombre.
            posBlanco = clientesDs.Clientes[0].apellidoyNombre.IndexOf(" ");

            txtApellido.Text = clientesDs.Clientes[0].apellidoyNombre.Substring(0, posBlanco);
            txtNombre.Text = clientesDs.Clientes[0].apellidoyNombre.Substring(posBlanco + 1, clientesDs.Clientes[0].apellidoyNombre.Length - (posBlanco + 1));

            txtCuit.Text = clientesDs.Clientes[0].cuit;
            txtProvincia.Text = clientesDs.Clientes[0].provincia;
            txtLocalidad.Text = clientesDs.Clientes[0].localidad;
            txtDireccion.Text = clientesDs.Clientes[0].direccion;
            txtTel.Text = clientesDs.Clientes[0].tel;
            txtCel.Text = clientesDs.Clientes[0].cel;
            txtEmail.Text = clientesDs.Clientes[0].email;
            txtDescuento.Text = clientesDs.Clientes[0].descuento.ToString();
            //..
            //...
            //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.


        }

        private void txtDni_KeyDown(object sender, KeyEventArgs e) //metodo que captura el evento enter sobre el txtDni
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (estadoDelFormulario == "estEsperandoOperacion") //estado esperando operación o estado inicial
                {
                    eventoBusDni();

                }

                else //estado agregar o editar
                {
                    procesar();
                }

            }
        }

        private void txtApellido_TextChanged(object sender, EventArgs e) //evento que se desencadena cuando cambia el valor del TextBox
        {
            if (this.estadoDelFormulario == "estEsperandoOperacion") //el proceso es capturado solo si está en este estado.
            {
                eventoBusApellidoNombre();
            }
        }

        protected void eventoBusApellidoNombre()
        {
            if (txtApellido.Text != "") //Si txtApellido es distinto de blanco se realiza el procesamiento. Esto se realiza para no perder el tiempo en filtro innecesarios.
            {
                if (refrescarResgClientes)   //si es necesario actualizar el resgClientes se lo hace sino no
                {
                    ejecutarHiloActualizarResgClientes();
                }

                ejecutarHiloFiltrarApellidoNombre();

                if (lstClientesApellidoNombre.Items.Count == 0)  //el filtro no obtuvo coincidencias, no se muestra el lstClientesApellidoNombre
                {
                    lstClientesApellidoNombre.Visible = false;
                    lstClientesApellidoNombre.Enabled = false;

                }
                else
                {
                    lstClientesApellidoNombre.Visible = true; //si se obtuvo una o más coincidencia se muestran en lstClientesApellidoNombre, y espera a que el usuario seleccione una.
                    lstClientesApellidoNombre.Enabled = true;

                }

            }
            else  //Si txtApellido es blanco no se realiza el procesamiento
            {
                lstClientesApellidoNombre.Enabled = false;
                lstClientesApellidoNombre.Visible = false;
            }
        }

        protected void ejecutarHiloFiltrarApellidoNombre()
        {
            if ((this.oHiloFiltrarApellidoNombre.ThreadState == ThreadState.Unstarted) || (this.oHiloFiltrarApellidoNombre.ThreadState == ThreadState.Stopped))
            {
                this.oHiloFiltrarApellidoNombre = new Thread(new ThreadStart(filtrarApellidoNombre)); //Instancia el hilo y lo delega al metodo filtrarApellidoNombre. 
                this.oHiloFiltrarApellidoNombre.Priority = ThreadPriority.AboveNormal;
                this.oHiloFiltrarApellidoNombre.Start();  //hilo que filtra los apellidosNombres asociadas al valor del txtApellido y lo carga en lstClientesApellidoNombre
            }

        }

        protected void filtrarApellidoNombre()
        {
            
            lstClientesApellidoNombre.Items.Clear(); //vaciamos el lstClientesApellidoNombre por si tuviera apellidosNombres anteriores.


            foreach (Cliente unCliente in resgClientes) //buscamos los apellidosNombre que coinciden con (al menos una palabra o letra + txtApellido.text + ninguna o muchas palabras o letras) y la cargamos en el lstApellidoNombre
            {
                try
                {
                    if (Regex.Match(unCliente.ApellidoNombre, txtApellido.Text.Trim().ToUpper()).Success)
                    {
                        lstClientesApellidoNombre.Items.Add(unCliente.ApellidoNombre);
                    }
                }
                catch (Exception)
                {
                    txtApellido.Text = "";

                }

            }

        }

        private void txtApellido_KeyDown(object sender, KeyEventArgs e) //Método que captura el evento de presión de una tecla sobre txtApellido
        {
            if ((e.KeyCode == Keys.Down) & (lstClientesApellidoNombre.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstClientesDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
            {

                lstClientesApellidoNombre.SetSelected(0, true); //se deja seleccionado el primer items
                lstClientesApellidoNombre.Focus(); //Se deja el foco sobre este control para que seleccione un items.

            }
            else
            {
                if ((e.KeyCode == Keys.Enter) & (this.estadoDelFormulario != "estEsperandoOperacion"))
                {
                    procesar();  //Si se presiona enter estando en estado Agregar o Editar
                }

            }
        }

        private void lstClientesApellidoNombre_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosDescripcion cuando el control pierde el foco.
        {
            this.lstClientesApellidoNombre.Enabled = false;
            this.lstClientesApellidoNombre.Visible = false;
        }

        private void lstClientesApellidoNombre_DoubleClick(object sender, EventArgs e) //evento que captura la elección de un item en el lstClientesApellidoNombre
        {
            procesarEleccionLstClientesApellidoNombre();
        }

        protected virtual void procesarEleccionLstClientesApellidoNombre()  //Se encapsula para que capture Double click y Enter sobre  lstClientesApellidoNombre
        {
            try
            {
                this.estadoDelFormulario = "Buscando";

                cargarClientesPorApellidoNombre(lstClientesApellidoNombre.SelectedItem.ToString()); //busca cliente por apellidoNombre y lo carga en los textBox.

                resguardarClienteActual(); //Guarda los valores de los textBox luego de una busqueda exitosa.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        private void btnAgregar_Click(object sender, EventArgs e)
        {

            if (estadoDelFormulario == "estEsperandoOperacion")
            {
                if (AccesoInternet())
                {
                    resguardarClienteActual(); //se resguarda el cliente que se estaba mostrando, por si no registra cambios. Aunque sea blanco no importa.

                    vaciarTextBox(); //vaciamos los txtBox

                    estAgregar();  //deja en estado agregar
                
                } else
                
                {
                    if (!AccesoInternet())
                    {
                        MessageBox.Show("Esta operación necesita conexión a internet.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    }
                }
                
            }
            else
            {
                deshacerCambios();  //vuelve a cargar el cliente que se mostraba antes en ultima busqeda exitosa.

                estEsperandoOperacion();

            }



        }

        private void btnEditar_Click(object sender, EventArgs e)
        {

            if (estadoDelFormulario == "estEsperandoOperacion")
            {
                if (AccesoInternet())
                {
                    deshacerCambios();  //vuelve a cargar el cliente que se mostraba antes, en la última busqueda exitosa

                    estEditar();  //deja en estado editar
                
                } else
                
                {
                    if (!AccesoInternet())
                    {
                        MessageBox.Show("Esta operación necesita conexión a internet.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    }
                }

                
            }
            else
            {
                deshacerCambios();  //vuelve a cargar el producto que se mostraba antes.

                estEsperandoOperacion();
            }

        }

        private void btnProcesar_Click(object sender, EventArgs e)
        {
            if (AccesoInternet())
            {
                procesar();
            }
            else
            {
                if (!AccesoInternet())
                {
                    MessageBox.Show("Esta operación necesita conexión a internet.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                }
            }
            
        }

        //Permite redefinir el comportamiento de este boton en frmAltaProductosDisueltos
        protected virtual void procesar() //se encapsulo en un método para usar cuando se presiona Enter con los textBox
        {
            if (estadoDelFormulario == "estAgregar") //estado agregar
            {
                if (formularioValido())
                {
                    try
                    {
                        agregarCliente();

                    }
                    catch (IndexOutOfRangeException)
                    {

                    }
                    catch (Exception ex)
                    {
                        //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                        MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                        //Si llega a ocurrir algún error en estado agregar 
                        this.Close();
                    }

                }
                else
                {
                    informarExistenciaError();
                }

            }
            else  //estado editar
            {
                if (formularioValido())
                {
                    try
                    {
                        editarCliente();

                    }
                    catch (IndexOutOfRangeException)
                    {

                    }
                    catch (Exception ex)
                    {
                        //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                        MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                        //Si llega a ocurrir algún error en estado agregar 
                        this.Close();
                    }

                }
                else
                {
                    informarExistenciaError();
                }
            }
        }

        protected virtual void editarCliente()
        {
            DialogResult result = MessageBox.Show("¿Desea actualizar el siguiente cliente? \nDni: " + resgClienteActual[0] + ", - Apellido Nombre: " + resgClienteActual[1], "CONFIRMACION EDICION DE CLIENTE", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {

                //FIJATE SI ESTÁ TODO BIEN. QUE COINCIDA CON TU CONSULTA
                clientesTa.FillByDni(clientesDs.Clientes, resgClienteActual[0]);  //el argumento corresponde con el dni actual del cliente a editar.

                clientesDs.Clientes[0].direccion = txtDireccion.Text.Trim().ToUpper();
                clientesDs.Clientes[0].tel = txtTel.Text.Trim().ToUpper();
                clientesDs.Clientes[0].cel = txtCel.Text.Trim().ToUpper();
                clientesDs.Clientes[0].email = txtEmail.Text.Trim().ToUpper();
                

                clientesTa.Update(clientesDs.Clientes);

                txtDireccion.Text = txtDireccion.Text.Trim().ToUpper();
                txtEmail.Text = txtEmail.Text.Trim().ToUpper(); //se coloca el email, en el formato correcto.

                //Se muestra un mje de confirmación.
                MessageBox.Show("Cliente editado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                refrescarResgClientes = true;  //como se agregó un cliente el resgClientes está desactualizado.

                resguardarClienteActual(); //Se resguarda el cliente actual editado correctamente.

                estEsperandoOperacion(); //Luego de insertar un cliente se vuelve al estado esperando operación. Para que pueda editarlo rapidamente.

            }
        }

        protected virtual void agregarCliente()
        {
            DialogResult result = MessageBox.Show("¿Está seguro en ingresar el nuevo cliente?.", "CONFIRMACION INGRESO DE CLIENTES", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {

                //(ALE)FIJATE SI ESTÁ TODO BIEN. QUE COINCIDA CON TU CONSULTA
                clientesTa.InsertQueryCliente(txtDni.Text.Trim(), txtApellido.Text.Trim().ToUpper() + " " + txtNombre.Text.Trim().ToUpper(),txtProvincia.Text.Trim().ToUpper(),txtLocalidad.Text.Trim().ToUpper(),txtDireccion.Text.Trim().ToUpper(),txtCuit.Text.Trim(),txtTel.Text.Trim(),txtCel.Text.Trim(),txtEmail.Text.Trim().ToUpper(),Convert.ToInt32(txtDescuento.Text),0);
                
                //Se muestra un mje de confirmación.
                MessageBox.Show("Cliente ingresado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                refrescarResgClientes = true;  //como se agregó un cliente el resgClientes está desactualizado.

                darFormatoADatos(); //Arregla los valores pasando a mayuscula, dejando como quedó en la base de datos.

                resguardarClienteActual(); //Se resguarda el cliente actual insertado correctamente.

                estEsperandoOperacion(); //Luego de insertar un cliente se vuelve al estado esperando operación. Para que pueda editarlo o eliminarlo rapidamente.
            }

        }

        private void darFormatoADatos()
        {
            txtDni.Text = txtDni.Text.Trim();
            txtApellido.Text = txtApellido.Text.Trim().ToUpper();
            txtNombre.Text = txtNombre.Text.Trim().ToUpper();
            txtCuit.Text = txtCuit.Text.Trim();
            txtProvincia.Text = txtProvincia.Text.Trim().ToUpper();
            txtLocalidad.Text = txtLocalidad.Text.Trim().ToUpper();
            txtDireccion.Text = txtDireccion.Text.Trim().ToUpper();
            txtTel.Text = txtTel.Text.Trim().ToUpper();
            txtCel.Text = txtCel.Text.Trim().ToUpper();
            txtEmail.Text = txtEmail.Text.Trim().ToUpper();
            txtDescuento.Text = txtDescuento.Text.Trim().ToUpper();

        }

        protected virtual bool formularioValido()
        {

            if (estadoDelFormulario == "estAgregar")
            {
                validarDni();

                validarApellidoNombre();

                validarCuit();

                validarProvincia();

                validarLocalidad();

                validarDireccion();

                validarTel();

                validarCel();

                validarEmail();

                validarDescuento();

            }
            else    //estEditar. Cuando se edita solo se controla estos valores
            {
                validarDireccion();

                validarTel();

                validarCel();

                validarEmail();
            }



            if ((errorProvider1.GetError(txtDni) == "") & (errorProvider1.GetError(txtApellido) == "") & (errorProvider1.GetError(txtCuit) == "") & (errorProvider1.GetError(txtProvincia) == "") & (errorProvider1.GetError(txtLocalidad) == "") & (errorProvider1.GetError(txtDireccion) == "") & (errorProvider1.GetError(txtTel) == "") & (errorProvider1.GetError(txtCel) == "") & (errorProvider1.GetError(txtEmail) == "") & (errorProvider1.GetError(txtDescuento) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarDni()
        {
            if (txtDni.Text.Trim() == "")
            {
                errorProvider1.SetError(txtDni, "Dni: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(txtDni, new ValidarDatos().validarDni("Dni", txtDni.Text) + validarDuplDni(0));
            }

        }

        private void validarApellidoNombre()
        {
            errorProvider1.SetError(txtNombre, new ValidarDatos().validarLongitud("Nombre",txtApellido.Text + txtNombre.Text,100));
        }

        private void validarCuit()
        {
            if (txtEmail.Text == "")
            {
                errorProvider1.SetError(txtCuit, "");
            }else
            {
                errorProvider1.SetError(txtCuit, new ValidarDatos().validarCuit("Cuit:", txtCuit.Text));
            }
            
        }

        private void validarProvincia()
        {
            errorProvider1.SetError(txtProvincia, new ValidarDatos().validarLongitud("Provincia", txtProvincia.Text, 30));
        }

        private void validarLocalidad()
        {
            errorProvider1.SetError(txtLocalidad, new ValidarDatos().validarLongitud("Localidad", txtLocalidad.Text, 30));
        }

        private void validarDireccion()
        {
            if (txtDireccion.Text.Trim() == "")
            {
                errorProvider1.SetError(txtDireccion, "Dirección: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(txtDireccion, new ValidarDatos().validarLongitud("Dirección", txtDireccion.Text,100));
            }
        }

        private void validarTel()
        {
            errorProvider1.SetError(txtTel, new ValidarDatos().validarLongitud("Tel:", txtTel.Text, 25));
        }

        private void validarCel()
        {
            errorProvider1.SetError(txtCel, new ValidarDatos().validarLongitud("Cel:", txtTel.Text, 25));
        }

        private void validarEmail()
        {
            if (txtEmail.Text == "")
            {
                errorProvider1.SetError(txtEmail, "");
            }else
            {
                errorProvider1.SetError(txtEmail, new ValidarDatos().validarLongitud("E-mail:", txtEmail.Text, 50) + new ValidarDatos().validarMail("E-mail:", txtEmail.Text)); 
            }
            
        }

        private void validarDescuento()
        {
            errorProvider1.SetError(txtDescuento, new ValidarDatos().validarNaturales("% Descuento", txtDescuento.Text));
        }

        protected virtual string validarDuplDni(int maxCoincidencia) //valida que no exista otro cliente con este dni. El argumento define el maximo de coincidencia que puede aceptarse.
        {
            
            int coincidencia = 0;


            foreach (Cliente unCliente in resgClientes) //buscamos  que coinciden con (una T + un caracter blanco + txtDescripcion.text) y la cargamos en el lstProductosDescripcion
            {
                if (unCliente.Dni == txtDni.Text.Trim().ToUpper())
                {
                    coincidencia++;
                }

            }

            if (coincidencia > maxCoincidencia)
            {
                return "Dni: ya existe otro cliente con este dni.";
            }
            else
            {
                return "";
            }

        }

        protected void presionoEnter(object sender, System.Windows.Forms.KeyEventArgs e) //captura el evento KeyDown. Cuando se presiona la tecla Enter en los textBox nombre, cuit, provincia, localidad, direccion, tel, cel, email, descuento
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesar();
            }

        }

        public bool AccesoInternet()  //verifica si existe conexión a internet.
        {
            try
            {
                System.Net.IPHostEntry host = System.Net.Dns.GetHostEntry("www.google.com");
                
                return true;
            }
            catch (Exception)
            {
                return false;
                
            }
        }

       
        private void btnBusApellido_Click(object sender, EventArgs e) //metodo que captura el evento click sobre la lupa btnBusApellido
        {
            eventoBusApellidoNombre();
        }

        private void lstClientesApellidoNombre_KeyDown(object sender, KeyEventArgs e) //metodo que captura el evento keyDown sobre el lstClientesApellidoNombre, cuando presiona enter y hacia arriba en el primer items.
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstClientesApellidoNombre();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstClientesApellidoNombre.SelectedIndex == 0)) //si llega al primer lugar y presiona para arriba, vuelve al txtApellido
                {
                    txtApellido.Focus();
                }

            }
        }




    }
}
